import format.amf.Value;
import format.flv.Data;
import hxvid.events.ConnectionEvent;
import hxvid.IApplication;
import hxvid.Client;
import hxvid.Logger;
import hxvid.Rtmp;
import hxvid.Commands;
import hxvid.Data;
import hxvid.Server;
import hxvid.SharedObject;

typedef User=
{
	var id:Int;
	var name:String;
}

class Application implements IApplication
{
	public var config:ApplicationConfig;
	public var clients:Array<Client>;
	
	private var server:Server;
	private var clientID:Int;
	private var logger:Logger;
	
	public function new(server:Server, config:ApplicationConfig)
	{
		this.server = server;
		this.config = config;
		
		this.clientID = 0;
		this.clients = new Array();
		logger = new Logger(config.logFile);
		logger.id = "chat/Application";
		logger.info("started");
		//server.addEventListener(ServerEvent.CLIENT_CONNECT, onBeforeConnect);
	}
	public function onConnect(client:Client, obj:ConnectionObject, ?arg:Dynamic=null):Void
	{
		logger.info("onConnect client:"+ client.ip);
		client.addEventListener(ConnectionEvent.CONNECTED, onConnected);
		client.addEventListener(ConnectionEvent.DISCONNECTED, onClientDisconnect);
		clients.push(client);
		client.addCommands(
		[
			["login", this.login, T.Null, T.String ],
			["textInput", this.textInput, T.Null, T.String ],
			["getUsers", this.getUsers, T.Null ],
			["isTyping", this.isTyping, T.Null ]
		]);
		client.accept();
	}
	function onConnected(event:ConnectionEvent):Void
	{
		logger.info("onConnected client:" + event.target.ip + " has received NetConnection.Connect.Success)");
	}
	function login(cinf:CommandInfos, _ ,name:String):Void
	{	
		var client:Client = cinf.c;
		logger.info("login attempt by client:"+client.ip +", with name:"+ name);
		
		if(!checkUserName(name))
		{
			client.sendResult(cinf, false);
		}
		else
		{
			client.sendResult(cinf, true);
			client.id = clientID++;
			client.name = name;
			for (c in clients)
			{
				c.send2("userJoin", Date.now(), {id:client.id, name:client.name});
			}
		}
	}
	function textInput(cinf:CommandInfos, _ , text:String):Void
	{
		var client:Client = cinf.c;
		logger.info("textInput sent by client:"+client.ip +", text:"+ text);
		for (c in clients)
		{
			c.send3("textInput", Date.now(), {id:client.id, name:client.name}, text);
		}
	}
	function getUsers(cinf:CommandInfos, _ ):Void
	{
		var client:Client = cinf.c;
		logger.info("getUsers requested by client:"+client.ip);
		var out:Array<User> =[];
		for (c in clients)
			if(c.id!=null)
				out.push({id:c.id, name:c.name});
		client.sendResult(cinf, out);
	}
	function isTyping(cinf:CommandInfos, _ ):Void
	{
		var client:Client = cinf.c;
		logger.info("isTyping sent by client:"+client.ip);
		for (c in clients)
		{
			c.send1("isTyping", {id:client.id, name:client.name});
		}
	}
	function checkUserName(name:String):Bool
	{
		for (c in clients)
			if(c.name==name)
				return false;
		return true;
	}
	public function onClientDisconnect(event:ConnectionEvent)
	{
		var client = event.target;
		logger.info("onClientDisconnect client:" +client.ip+", id:"+client.id + ", name:" + client.name);
		var user = {id:client.id, name:client.name};
		for (i in 0...clients.length)
		{
			if(clients[i]==client)
			{
				clients.splice(i,1);
				break;
			}
		}
		for (c in clients)
		{
			c.send2("userLeave", Date.now(), user);
		}
	}
}